<template>
    <el-select
        v-get-ref="getRefFn"
        :ref="selectOptions.ref"
        v-model="show"
        :multiple="selectOptions.multiple"
        :multiple-limit="selectOptions.multipleLimit"
        :disabled="selectOptions.disabled"
        :collapse-tags="selectOptions.collapseTags"
        :placeholder="selectOptions.placeholder"
        :size="selectOptions.size"
        :clearable="selectOptions.clearable"
        :filterable="selectOptions.filterable"
        :remote="selectOptions.remote"
        :reserve-keyword="selectOptions.reserveKeyword"
        :allow-create="selectOptions.allowCreate"
        :loading="selectOptions.loading"
        :loading-text="selectOptions.loadingText"
        :no-match-text="selectOptions.noMatchText"
        :default-first-option="selectOptions.defaultFirstOption"
        :value-key="selectOptions.valueKey"
        @change="changeEvent"
        @focus="focusEvent"
        @visible-change="visibleChange"
        :remote-method="remoteMethod"
        :popper-class="popperClass"
        @clear="clearHandle"
        @remove-tag="removeTag"
        class="my-Select"
        style="width: 100%">
        <template slot>
            <template v-if="selectOptions.multiple || (!selectOptions.tree && $utils.isNotEmptyList(data_list))">
                <el-option class="select-item"
                    v-for="(item, index) in data_list"
                    :key="index"
                    :label="item[selectOptions.props.label]"
                    :value="item[selectOptions.props.value]"
                    :disabled="item[selectOptions.props.disabled]"
                />
            </template>
            <template v-else>
                <el-option :value="showValue" :label="show" class="options">
                    <vTreeEdit ref="tree" :options="treeOptions" :treeData="data_list"
                               @event="handleTreeEvent" />
                </el-option>
            </template>
        </template>
        <template slot="empty"></template>
    </el-select>
</template>

<script>
import selectBottomAction from "@common/components/module/selectBottomAction";
import { mapGetters, mapState } from "vuex";

export default {
    name: "vSelectEdit",
    mixins: [ selectBottomAction ], // 添加弹层底部操作按钮
    provide() {
        return {
            setChildrenRef: (name, ref) => {
                this[name] = ref;
            },
        };
    },
    inject: {
        setChildrenRef: {
            default: () => {
            },
        },
    },
    props: {
        model: {
            //操作对象
            type: Object,
            default() {
                return {};
            },
        },
        treeOptions: {
            //树配置对象
            type: Object,
            default() {
                return {};
            },
        },
        options: {
            //select配置
            type: Object,
            default() {
                return {};
            },
        },
        data_list: {
            //下拉框数据
            type: Array,
            default() {
                return [];
            },
        },
        value: [ String, Array ],
    },
    data() {
        return {
            showValue: [],
            show: this.value,
            selectOptions: {},
            defaultOptions: {
                tree: true,
                ref: "vSelectEdit",
                field: "value", //选择的值写入model的字段
                value: "id", //传空时整个选项的值
                label: "label", //value显示的字段
                multiple: false, //是否多选
                multipleLimit: 0, //多选时用户最多可以选择的项目数，为 0 则不限制
                disabled: false, //是否禁用
                collapseTags: true, //多选时是否将选中值按文字的形式展示
                placeholder: "请选择",
                size: "mini", // "small",
                clearable: true, //可启用清空功能，属性仅适用于单选。
                filterable: false, //可启用搜索功能
                remote: false, //是否为远程搜索
                reserveKeyword: false, //多选且可搜索时，是否在选中一个选项后保留当前的搜索关键词
                valueType: "Array", //值的类型，需要数组或者String
                allowCreate: false, //是否允许用户创建新条目，需配合 filterable 使用
                loading: false, //是否正在从远程获取数据
                loadingText: "加载中", //远程加载时显示的文字
                noMatchText: "无匹配数据", //
                popperClass: "popperClass ", //Select 下拉框的类名
                defaultFirstOption: false, //输入框按下回车，选择第一个匹配项。需配合 filterable 或 remote 使用
                valueKey: "value", //作为 value 唯一标识的键名，绑定值为对象类型时必填
                props: {
                    //option参数配置
                    key: "value",
                    label: "name",
                    value: "value",
                    disabled: "disabled",
                },
                // bottomAction: {
                //   //底部按钮配置 需要底部按钮的 配置bottomAction参数
                //   label: "新增",
                //   icon: "",
                //   click: this.addUnit,
                // },
            },
        };
    },
    watch: {
        options: {
            handler() {
                this.initOptions(this.options);
            },
            deep: true,
            immediate: true,
        },
        value: {
            handler() {
                this.initShow();
            },
            deep: true,
            immediate: true,
        },
        data_list: {
            handler() {
                this.initShow();
            },
            deep: true,
        },
    },
    computed: {
        children() {
            let _this = this;
            if (_this.treeOptions.props && _this.treeOptions.props.children) {
	            return _this.treeOptions.props.children;
            }
            return "children";
        },
        popperClass() {
            let str = this.selectOptions.popperClass;
            if (!this.selectOptions.multiple) {
                return (
                    (!this.selectOptions.tree ? "select_option " : "") +
                    "my-Select " +
                    str
                );
            }
            return (!this.selectOptions.tree ? "select_option " : "") + str;
        },
        ...mapGetters([ "getSidByPath" ]),
        ...mapState([ "permission" ]),
    },
    created() {
        let _this = this;
        _this.initOptions(_this.options);
    },
    methods: {
        getRefFn(v) {
            typeof this.setChildrenRef === 'function' && this.setChildrenRef(this.selectOptions.ref, v);
        },
        visibleChange(v) {
            let $this = this;
            if ($this.selectOptions.bottomAction) {
                // 权限控制
                let action = $.extend({}, $this.selectOptions.bottomAction);
                let actionPermission = true;
                if (this.$utils.isNotEmpty(action.permission)) {
                    actionPermission = false;
                    if (this.$utils.isNotEmpty(action.permissionUrl)) {
                        let sid = $this.getSidByPath(action.permissionUrl);
                        if ($this.$utils.isNotEmpty(sid)) {
                            let permissionList = $this.permission[sid];
                            actionPermission = permissionList.map(item => item.permission || item).indexOf(action.permission) !== -1;
                        }
                    }
                }
                if (actionPermission) {
                    this.selectBottomAction(v, $this.data_list, {
                        ref: this.selectOptions.ref,
                        label: this.selectOptions.bottomAction.label,
                        icon: this.selectOptions.bottomAction.icon,
                        click: this.selectOptions.bottomAction.click,
                    });
                }
            }
            this.$emit('event', {
                type: 'visibleChange',
                value: v,
            });
        },
        initOptions(options) {
            let _this = this;
	        _this.selectOptions = $.extend(true, {}, _this.defaultOptions, options);
        },
        initShow() {
            //初始化显示
            let _this = this;
            let multiple = _this.selectOptions.multiple;
            _this.show = multiple ? [] : null;
            let value = this.value;
            if (_this.$utils.isNotEmpty(value) || value === 0) {
                let fields = [];
                let array = _this.data_list;
                if (_this.$XEUtils.isArray(value)) {
                    fields = value.map((item) => {
                        if (_this.$XEUtils.isPlainObject(item)) {
                            //判断是否是一个对象
                            return item;
                        } else return { [_this.selectOptions.props.value]: item };
                    });
                } else {
                    let obj = {};
                    obj[_this.selectOptions.props.value] = value;
                    fields.push(obj);
                }
                for (let item of fields) {
                    // valueArr =
                    // this.$XEUtils.searchTree(
                    this.$XEUtils.eachTree(array, (element) => {
                            if (_this.selectOptions.props.value) {
                                // 比较两个对象的属性值是否一致
                                if (item[_this.selectOptions.props.value] === element[_this.selectOptions.props.value]) {
                                    // 多选情况下push进显示数组，单选直接显示赋值
                                    if (multiple) {
                                        _this.show.push(element[_this.selectOptions.props.value]);
                                    } else {
                                        _this.show = element[_this.selectOptions.props.label];
                                    }
                                    return true;
                                } else {
                                    return false;
                                }
                            } else {
                                // 比较两个对象是否一致
                                if (_this.$XEUtils.isEqual(item, element)) {
                                    // 多选情况下push进显示数组，单选直接显示赋值
                                    if (multiple) {
                                        _this.show.push(element[_this.selectOptions.props.value]);
                                    } else {
                                        _this.show = element[_this.selectOptions.props.label];
                                    }
                                } else return false; //比较两个对象是否一致
                            }
                        }, {
                            children: _this.children,
                        }
                    );
                }
            }
			this.initOptions(this.options);
            this.initScroll();
            this.$forceUpdate();
        },
        // 多选模式下移除tag时触发
        removeTag(val) {
            this.$emit('event', {
                type: 'removeTag',
                value: val,
            });
        },
        changeEvent(e) {
            if (!this.$utils.isNotEmptyList(this.data_list)) {
                this.show = null;
                return;
            }
            let arrNew = [];
            let dataLength = this.showValue.length;
            let eleng = e.length;
            for (let i = 0; i < dataLength; i++) {
                for (let j = 0; j < eleng; j++) {
                    if (e[j] === this.showValue[i][this.selectOptions.props.label]) {
                        arrNew.push(this.showValue[i][this.selectOptions.props.value]);
                    }
                }
            }
            if (this[this.treeOptions.ref]) {
                this[this.treeOptions.ref].setCheckedKeys(arrNew, false); //设置勾选的值
            }
            this.$emit("select", this.show);
            this.$emit("event", this.show);
        },
        remoteMethod(query) {
            if (this.selectOptions.remoteMethod && typeof this.selectOptions.remoteMethod === "function") {
                return this.selectOptions.remoteMethod(query);
            }
        },
        focusEvent() {
            let _this = this;
            // _this.$refs[_this.selectOptions.ref].showPanel();
        },
        // 初始化滚动条
        initScroll() {
            this.$nextTick(() => {
                let scrollWrap = document.querySelectorAll(
                    ".el-scrollbar .el-select-dropdown__wrap"
                )[0];
                let scrollBar = document.querySelectorAll(
                    ".el-scrollbar .el-scrollbar__bar"
                );
                // scrollWrap.style.cssText =
                //   "margin: 0px; max-height: none; overflow: hidden;";
                scrollBar.forEach((ele) => (ele.style.width = 0));
            });
        },
        // 清除选中
        clearHandle() {
            let _this = this;
            let multiple = _this.selectOptions.multiple;
            _this.show = multiple ? [] : "";
            let value = _this.show;
            this.$emit("input", value);
            this.dispatch('ElFormItem', 'el.form.change', value)
            this.clearSelected();
            this.$emit("event", { type: 'clear' });
        },
        // 清空选中样式
        clearSelected() {
            let allNode = document.querySelectorAll("#tree-option .el-tree-node");
            allNode.forEach((element) => element.classList.remove("is-current"));
        },
        keyupEvent(event) {
        },
        handleTreeEvent(event) {
            let _this = this;
            let data = [];
            let show = [];
            let value = [];
            if (event.type === "nodeClick") {
                if (_this.selectOptions.multiple !== true) {
                    if (event.data) {
                        data.push(event.data);
                    }
                }
            } else if (event.type === "checkClick") {
                data = event.ref.getCheckedNodes();
            }
            _this.$emit("event", event, data);
            // console.log("event", event, data,);
            _this.handleData(data);
        },
        handleData(data) {
            let _this = this;
            let show = []; //存放lable
            let value = []; //存放value
            let showValue = []; //存放item
            if (data && data.length) {
                data.forEach((item) => {
                    showValue.push(item);
                    show.push(item[_this.selectOptions.props.label]);
                    if (_this.selectOptions.props.value) {
                        value.push(item[_this.selectOptions.props.value]);
                    }
                });
                if (_this.selectOptions.multiple !== true) {
                    [ show ] = show;
                    [ value ] = value;
                }
            }
            _this.show = show; //显示的值
            // _this.showValue = value;
            _this.showValue = showValue;
            // console.log("data", data, show, value, showValue);
            this.$emit("input", value);
            this.dispatch('ElFormItem', 'el.form.change', value)
            if (_this.selectOptions.multiple !== true) {
                _this.$refs[_this.selectOptions.ref].blur();
            }
        },
    },
};
</script>
<style scoped>
.my-dropdown {
    max-height: 30vh;
    min-width: 200px;
    min-height: 100px;
    overflow: auto;
    background-color: #fff;
    padding: 0 0 10px 0;
    border: 1px solid #dcdfe6;
    box-shadow: 0 0 6px 2px rgba(0, 0, 0, 0.1);
}

.tree,
.my-Select {
    width: 100%;
}

.el-scrollbar .el-scrollbar__view .el-select-dropdown__item {
    height: auto;
    max-height: 30vh;
    padding: 0;
    overflow: hidden;
    overflow-y: auto;
    margin: -6px 0;
}

.select_option .el-scrollbar .el-scrollbar__view .select-item {
    padding: 0 20px;
}

.el-select-dropdown__item.selected {
    font-weight: normal;
}

ul li >>> .el-tree .el-tree-node__content {
    height: auto;
    padding: 0 20px;
}

.el-tree-node__label {
    font-weight: normal;
}

.el-tree >>> .is-current .el-tree-node__label {
    color: #409eff;
    font-weight: 700;
}

.el-tree >>> .is-current .el-tree-node__children .el-tree-node__label {
    color: #606266;
    font-weight: normal;
}

>>> .el-select-dropdown {
    max-height: 30vh;
    min-width: 200px;
    min-height: 100px;
    overflow: auto;
    margin: -6px 0;
}

/deep/ .el-select-dropdown .treeEdit {
    max-height: 30vh;
    min-width: 200px;
    min-height: 100px;
    overflow: auto;
    padding: 0;
}
</style>
<style>
</style>
